package com.wh.process.bprocessdefinition;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.apache.commons.io.FileUtils;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

/**
 * activiti流程定义的CRUD
 *
 * @author WeiHong
 * @date 2018/4/27
 */
public class ProcessDefinitionTest {

    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    /**
     * 部署流程定义 by class
     */
    @Test
    public void deploymentProcessDefinitionByClass() {
        //与流程定义和部署对象相关的service
        Deployment deployment = processEngine.getRepositoryService()
                //创建一个部署对象
                .createDeployment()
                //添加部署名称
                .name("流程定义")
                //从classpath的资源中加载，一次只能加载一个文件
                .addClasspathResource("diagrams/MyProcess.bpmn")
                .addClasspathResource("diagrams/MyProcess.png")
                //完成部署
                .deploy();
        System.out.println("部署ID = " + deployment.getId());
        System.out.println("部署名称 = " + deployment.getName());
    }

    /**
     * 部署流程定义
     */
    @Test
    public void deploymentProcessDefinitionByZip() {
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("diagrams/MyProcess.zip");
        ZipInputStream zipInputStream = new ZipInputStream(in);
        Deployment deployment = processEngine.getRepositoryService().createDeployment().name("流程定义").addZipInputStream(zipInputStream).deploy();
        System.out.println("部署ID = " + deployment.getId());
        System.out.println("部署名称 = " + deployment.getName());
    }

    /**
     * 流程定义查询
     */
    @Test
    public void findProcessDefinition() {
        List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
                /**查询条件*/
                //.deploymentId(deploymentId)//使用部署对象ID查询
                //.processDefinitionId(processDefinitionId)//使用流程定义ID查询
                //.processDefinitionKey(processDefinitionKey)//使用流程定义的key查询
                //.processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
                /**排序*/
                .orderByProcessDefinitionVersion().asc()//按照版本的升序排列
                //.orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
                /**返回的结果集*/
                .list();//返回一个集合列表，封装流程定义
        //.singleResult();//返回惟一结果集
        //.count();//返回结果集数量

        for (ProcessDefinition pd : list) {
            //流程定义的key+版本+随机生成数
            System.out.println("流程定义ID:" + pd.getId());
            //对应.bpmn文件中的name属性值
            System.out.println("流程定义的名称:" + pd.getName());
            //对应.bpmn文件中的id属性值
            System.out.println("流程定义的key:" + pd.getKey());
            //当流程定义的key值相同的相同下，版本升级，默认1
            System.out.println("流程定义的版本:" + pd.getVersion());
            System.out.println("资源名称bpmn文件:" + pd.getResourceName());
            System.out.println("资源名称png文件:" + pd.getDiagramResourceName());
            System.out.println("部署对象ID：" + pd.getDeploymentId());
            System.out.println("#########################################################");
        }
    }

    /**
     * 删除流程定义
     */
    @Test
    public void deleteProcessDefinition() {
        //部署ID
        String deploymentId = "1";
        /**
         * 不带级联的删除
         *    只能删除没有启动的流程，如果流程启动，就会抛出异常
         */
        /*processEngine.getRepositoryService().deleteDeployment(deploymentId);*/

        /**
         * 级联删除
         * 	  不管流程是否启动，都能可以删除
         */
        processEngine.getRepositoryService().deleteDeployment(deploymentId, true);

        System.out.println("删除完成 ：deploymentId = " + deploymentId);
    }

    /**
     * 查看流程图
     */
    @Test
    public void viewPic() throws IOException {
        //部署ID
        String deploymentId = "2501";
        /**
         * 获取图像名称
         */
        List<String> list = processEngine.getRepositoryService().getDeploymentResourceNames(deploymentId);

        String resourceName = "";
        for (String s :
                list) {
            if (s.indexOf(".png") > 0) {
                resourceName = s;
            }
        }
        //获取图片的输入流
        InputStream inputStream = processEngine.getRepositoryService().getResourceAsStream(deploymentId, resourceName);
        File f = new File("D:/" + resourceName);
        FileUtils.copyInputStreamToFile(inputStream, f);

    }

    /**
     * 查询最新版本的流程定义
     */
    @Test
    public void findLastVersionProcessDefinition() {

        List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery().orderByProcessDefinitionVersion().asc().list();
        /**
         *   Map<String,ProcessDefinition>
         *   map集合的key：流程定义的key
         *   map集合的value：流程定义的对象
         *   map集合的特点：当map集合key值相同的情况下，后一次的值将替换前一次的值
         */
        Map<String, ProcessDefinition> map = new LinkedHashMap<>(4);
        for (ProcessDefinition pd : list) {
            map.put(pd.getKey(), pd);
        }

        List<ProcessDefinition> pdList = new ArrayList<>(map.values());
        for (ProcessDefinition pd : pdList) {
            //流程定义的key+版本+随机生成数
            System.out.println("流程定义ID: " + pd.getId());
            //对应.bpmn文件中的name属性值
            System.out.println("流程定义的名称: " + pd.getName());
            //对应.bpmn文件中的id属性值
            System.out.println("流程定义的key: " + pd.getKey());
            //当流程定义的key值相同的相同下，版本升级，默认1
            System.out.println("流程定义的版本: " + pd.getVersion());
            System.out.println("资源名称bpmn文件: " + pd.getResourceName());
            System.out.println("资源名称png文件: " + pd.getDiagramResourceName());
            System.out.println("部署对象ID：" + pd.getDeploymentId());
            System.out.println("-----------------------------------------------------");
        }

    }

    /**
     * 删除流程定义（删除key相同的所有不同版本的流程定义）
     */
    @Test
    public void deleteProcessDefinitionByKey() {
        //流程定义的key
        String processDefinitionKey = "helloworld";
        List<ProcessDefinition> list = processEngine.getRepositoryService().createProcessDefinitionQuery()
                .processDefinitionKey(processDefinitionKey).list();
        for (ProcessDefinition pd : list) {
            //获取部署ID
            String deploymentId = pd.getDeploymentId();
            processEngine.getRepositoryService().deleteDeployment(deploymentId, true);
        }

    }


}
